home *** CD-ROM | disk | FTP | other *** search
/ Aminet 19 / Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso / Aminet / text / tex / rtf2latex.lha / rtf2LaTeX / rtf2LaTeX.c < prev    next >
C/C++ Source or Header  |  1997-02-28  |  66KB  |  2,755 lines

  1. /*
  2.  * An output filter to produce LaTeX using Paul DuBois' RTF reader
  3.  * WECHTL Erwin
  4.  * Woerthg. 2/18
  5.  * A-2500 Baden
  6.  * AUSTRIA
  7.  *
  8.  * a student of the University in vienna
  9.  * Technische Universitaet Wien
  10.  * Institut fuer Technische Informatik
  11.  * Treitlstr. 3
  12.  * A-1040 WIEN
  13.  * AUSTRIA
  14.  *
  15.  * Changed code from:
  16.  *
  17.  * Written and copyright (c) 1991 by Robert Lupton (rhl@astro.princeton.edu)
  18.  * Permission is granted to freely distribute and modify this code, providing:
  19.  *    1/ This copyright notice is preserved
  20.  *    2/ You send me a copy of any changes for inclusion in a future release
  21.  */
  22. #include <stdio.h>
  23. #include <ctype.h>
  24. #include <string.h>
  25. #ifdef __STDC__
  26. #   include <stdlib.h>
  27. #   ifndef THINK_C
  28. #      include <unistd.h>
  29. #   endif
  30. #else /* !__STDC__ */
  31. #   ifdef NO_MALLOC_H
  32.         extern char     *malloc ();
  33. #   else /* NO_MALLOC_H */
  34. #       include    <malloc.h>
  35. #   endif /* NO_MALLOC_H */
  36. #endif /* !__STDC__ */
  37. #ifndef SEEK_SET
  38. #   define SEEK_SET 0
  39. #endif
  40. #include "fonts.h"
  41. #include "r2L_version.h"
  42. #include "rtf2LaTeX.h"
  43. #include "rtf.h"
  44.  
  45. #ifdef THINK_C
  46. #include <console.h>
  47. #include "macintosh.h"
  48. static char * RTFDIR;
  49. #endif
  50.  
  51.  
  52. char *progname;    /* Used in Error messages */
  53. RTFFuncPtr default_read_font = NULL;    /* default func to read style table */
  54. RTFFuncPtr default_read_style = NULL;    /* default func to read style table */
  55.  
  56. /* This forward declaration isn't possible in the header file because
  57.  * RTFStyle isn't defined there yet.
  58.  */
  59. static int is_specialWORDstyle A((RTFStyle*,LATEXStyle*));
  60. /*****************************************************************************/
  61. int
  62. main(ac,av)
  63. int ac;
  64. char *av[];
  65. {
  66.    RTF_STACK rtf_initial;        /* initial values of things that
  67.                        on rtf stack */
  68.  
  69.    static char *header_erwinbet[] = {
  70.       "% Converted from RTF format using rtf2LaTeX",
  71.       "% Comments and bugs to Erwin Wechtl",
  72.       "%                      Woertg. 2/18",
  73.       "%                      A-2500 Baden",
  74.       "%",
  75.       NULL,
  76.    };
  77.  
  78.  
  79. FILE *fil = NULL;
  80. extern int optind;
  81. extern char *optarg;
  82. int c;
  83. char *codefile = "mac", *landfile = "english";
  84. char *str = "12345.67";
  85. char *rtf_filename = NULL;
  86.  
  87. #ifdef THINK_C
  88.    RTFDIR = get_home_dir();
  89.    ac = ccommand(&av);
  90. #endif /* THINK_C */
  91.  
  92.    progname = av[0];
  93.    while((c = getopt(ac,av,"cC:dhgGHL:npqrstT:uv:V")) != EOF)
  94.       {
  95.       switch (c)
  96.        {
  97.        case 'g':
  98.      german_squotes = 1;
  99.      break;
  100.        case 'G':
  101.      german_dquotes = 1;
  102.      break;
  103.        case 'q':
  104.      translate_quotes = 1;
  105.      break;
  106.        case 'C':
  107.      codefile = optarg;
  108.      break;
  109.        case 'c':            /* don't do character formating */
  110.      formatting_char= 0;
  111.      break;
  112.        case 'd':            /* formate also in specila WORD styles like heading, footer, footnote text, .. (default 0) */
  113.      formatting_sWORD = 1;
  114.      break;
  115.        case 'h':
  116.      usage();
  117.      exit(0);
  118.        case 'H':            /* use LaTeX default header and footer */
  119.      header_on = 0;
  120.      break;
  121.        case 'L':
  122.      landfile = optarg;
  123.      break;
  124.        case 'n':
  125.      other_linebreak = 1;           /* use \hfil\break instead of \\ */
  126.      break;                         /* for making a new line         */
  127.        case 'p':            /* don't do paragraph formating */
  128.      formatting_para =  0;
  129.      break;
  130.        case 'r':            /* ignore left and right skip */
  131.      rl_skip_on = 0;
  132.      break;
  133.        case 's':            /* ignore tab stops */
  134.      tabstops_on = 0;
  135.      break;
  136.        case 't':            /* don't do any formating in tables */
  137.      formatting_table =  0;
  138.      break;
  139.        case 'T':            /* decrease cell-width (default 0.7)*/
  140.      smaller_cell_factor=atof(optarg);
  141.      if (!(smaller_cell_factor > 0))
  142.         {
  143.         fprintf(stderr,"\n%s: Argument of the -T flag must be greater than 0,\n but it is %g\n", progname, smaller_cell_factor);
  144.         fprintf(stderr,"use -h for help\n");
  145.         exit(2);
  146.         }
  147.      break;
  148.        case 'u':            /* change underline to italic */
  149.      noUnderline = 1;
  150.      break;
  151.        case 'v':
  152.      verbose = atoi(optarg);
  153.      if (verbose!=1 && verbose!=2)
  154.         {
  155.         fprintf(stderr,"\n%s: The level of verbose can only be 1 or 2\n", progname);
  156.         fprintf(stderr,"use -h for help\n");
  157.         exit(2);
  158.         }
  159.      break;
  160.        case 'V':
  161.      fprintf(stderr,"%s: %s\n",progname,version);
  162.      exit(0);
  163.      break;
  164.        case '?':
  165.      fprintf(stderr,"%s: ", progname);
  166.      usage();
  167.      exit(2);
  168.       }
  169.     }
  170.   if (optind<ac)
  171.   {
  172.       if ((strchr(av[optind],'.')) != NULL)
  173.     rtf_filename = av[optind];
  174.       else
  175.       {
  176.     if((rtf_filename = malloc(strlen(av[optind]) + 5)) == NULL)
  177.     {
  178.         fprintf(stderr,"%s: Error in malloc\n", progname);
  179.         exit(3);
  180.     }
  181.     strcpy(rtf_filename, av[optind]);
  182.           strcat(rtf_filename,".rtf");
  183.       }
  184.   }
  185. #ifdef THINK_C
  186.   else rtf_filename = get_file_from_dialog();
  187.   if (!rtf_filename) exit(0);
  188. #endif
  189.   if(rtf_filename != NULL)
  190.   {
  191.       if((fil = fopen(rtf_filename,"r")) == NULL)
  192.       {
  193.      fprintf(stderr,"%s: Can't open %s\n",progname,rtf_filename);
  194.      exit(1);
  195.       }
  196.       RTFSetStream(fil);
  197.   }
  198.   if (optind+1<ac)
  199.     {
  200.     fprintf(stderr,"%s: After the filename (%s) there are no more arguments or flags allowed!\n", progname, av[optind]);
  201.     fprintf(stderr,"use -h for help\n");
  202.     exit(2);
  203.     }
  204.  
  205.    rtf_default.LaTeX_stack = NULL;    /* the rtf stack */
  206.    rtf_default.char_attr = char_attr;
  207.    rtf_default.par_attr = par_attr;
  208.    rtf_default.style = -1;
  209.    rtf_default.prev = NULL;
  210.    rtf_current = rtf_initial = rtf_default;
  211.    rtf_ptr=&rtf_default;
  212.    tabinitold[0]=tabinitnew[0]='\0';
  213.    Cformatting_char=formatting_char;
  214.    Cformatting_para=formatting_para;
  215.    tabstopsInit();
  216.    RTFInit();
  217.    read_code_file(codefile);        /* the file with the characters above 126
  218.                        files have the extension .code
  219.                        default file mac.code 
  220.                        use flag -C for other files
  221.                         e.g ansi.code*/
  222.    open_land_file(landfile);        /* the file with the special WORD styles 
  223.                        footer, footnote text, heading, ...
  224.                        files have the extension .land
  225.                        default file english.land
  226.                        use flag -L for other files
  227.                         e.g german.land    */
  228.    print_text(header_erwinbet,stdout);
  229.    output_str("\\documentstyle",'\0');
  230.    if(german_squotes || german_dquotes)
  231.        output_str("[german]",'\0');
  232.    output_str("{article}\n",'\0');
  233.    if(header_on)
  234.     {
  235.     output_str("\\pagestyle",'\0');
  236.     output_str("{myheadings}\n",'\0');
  237.     }
  238.    output_str("\\newlength{\\defaultparindent}\n",'\0');
  239.    output_str("\\setlength{\\defaultparindent}{\\parindent}\n",'\0');
  240.    default_read_font = RTFGetDestinationCallback(rtfFontTbl);
  241.  
  242.    (void)RTFSetClassCallback(rtfUnknown, UnknownClass);
  243.    (void)RTFSetClassCallback(rtfGroup, GroupClass);
  244.    (void)RTFSetClassCallback(rtfText, start_para);
  245.    (void)RTFSetClassCallback(rtfControl, ControlClass);
  246.    (void)RTFSetDestinationCallback(rtfPict, read_pict);
  247.  
  248.    RTFRead();
  249.    
  250.    if(rtf_group != 0) {
  251.       fprintf(stderr,"%s: End of file is in an unclosed RTF group (level %d)\n",
  252.           progname,rtf_group);
  253.    }
  254.    if(LaTeX_group != 0) {
  255.       fprintf(stderr,"%s: End of file is in an unclosed LaTeX group (level %d)\n",
  256.           progname,LaTeX_group);
  257.    }
  258.    if(quotecount % 2)
  259.    {
  260.       fprintf(stderr,"%s: Uneven number of quotes (%d) counted\n",
  261.           progname, quotecount);
  262.    }
  263.    if(fil != NULL) fclose(fil);
  264.    output_str("\\end{document}",'\0');
  265.    if (verbose)
  266.     fprintf(stderr,"\nIf there are any LaTeX errors or warnings,\n\
  267. have a look in the man page section troubleshooting \n\n");
  268.    return(0);
  269. }
  270. /*****************************************************************************
  271.  *
  272.  * Token class callbacks
  273.  */
  274. static void
  275. UnknownClass()
  276. {
  277.    fprintf(stderr,"%s: Unknown Token: %s\n",progname,rtfTextBuf);
  278. }
  279. /*****************************************************************************/
  280. static void
  281. GroupClass()
  282. {
  283.    switch (rtfMajor) {
  284.     case rtfBeginGroup:
  285.       if(initialised && !text_out) {
  286.      start_para();
  287.       }
  288.       if (!table_mode)        /*it's hard to know where the end of    */
  289.     end_table();          /*       a table is, maybe here           */
  290.       push_rtf_group();
  291.       rtf_group++;
  292.       break;
  293.     case rtfEndGroup:
  294.       if(--rtf_group == -1) {
  295.      fprintf(stderr,"%s: Unbalanced group\n", progname);
  296.       } else {
  297.      while(pop_LaTeX_stack()) continue;
  298.      pop_rtf_group();
  299.      if(end_of_par) {
  300.         end_para();
  301.      }
  302.       }
  303.       break;
  304.    }
  305. }
  306. static void
  307. initialise()
  308. {
  309.    inDefineStyle=TRUE;
  310.    DefineStyles();
  311.    inDefineStyle=FALSE;
  312.    if(pageno != 1) {
  313.       sprintf(buff,"\\setcounter{page}{%d}\n",pageno);
  314.       output_str(buff,'\0');
  315.    }
  316.    output_str("\n%*****************************************************************",'\0');
  317.    output_str("\n\\begin{document}\n",'\0');
  318.    tabstopsInit();
  319.    initialised = 1;            /* don't do it twice */
  320. }
  321. /*****************************************************************************/
  322. static void
  323. TextClass()
  324. {
  325.    output(rtfMajor,1);
  326. }
  327. /*****************************************************************************
  328.  *
  329.  * Process control symbol.
  330.  */
  331. static void
  332. ControlClass()
  333. {
  334.    switch (rtfMajor) {
  335.     case rtfVersion:
  336.       if(verbose) fprintf(stderr,"RTF version %d\n",rtfParam);
  337.       break;
  338.     case rtfDefFont:
  339.       default_font = rtfParam;        /* this may not be in the font table */
  340.       break;
  341.     case rtfCharSet:
  342.       CharSet ();
  343.       break;
  344.     case rtfDestination:
  345.       Destination();
  346.       break;
  347.     case rtfFontFamily:            /* only occurs within font table */
  348.       fprintf(stderr,"%s: You shouldn't see rtfFontType: minor %d\n",
  349.     progname,rtfMinor);
  350.       break;
  351.     case rtfColorName:            /* only occurs within color table */
  352.       fprintf(stderr,"%s: You shouldn't see rtfColorName: minor %d\n",
  353.     progname,rtfMinor);
  354.       break;
  355.     case rtfStyleAttr:            /* only occurs within stylesheet */
  356.       switch (rtfMinor) {
  357.        case rtfBasedOn:
  358.      if(rtfParam != rtfNoParam) {
  359.         static int count = 0;
  360.      
  361.         if(verbose > 1 || (verbose && count++ == 0)) {
  362.            msg_not_yet("sbasedon");
  363.         }
  364.      }
  365.      break;
  366.        case rtfNext:
  367.      if(rtfParam != rtfNoParam) {
  368.         static int count = 0;
  369.      
  370.         if(verbose > 1 || (verbose && count++ == 0)) {
  371.            msg_not_yet("snext");
  372.         }
  373.      }
  374.      break;
  375.        default:
  376.      fprintf(stderr,"%s: Illegal minor number for StyleAttr: %d\n",
  377.         progname,rtfMinor);
  378.      break;
  379.       }
  380.       break;
  381.     case rtfSpecialChar:
  382.       SpecialChar();
  383.       break;
  384.     case rtfDocAttr:
  385.       DocAttr();
  386.       break;
  387.     case rtfSectAttr:
  388.       SectAttr();
  389.       break;
  390.     case rtfTblAttr:
  391.       TblAttr();
  392.       break;
  393.     case rtfParAttr:
  394.       ParAttr();
  395.       break;
  396.     case rtfCharAttr:
  397.       if (Cformatting_char)
  398.           CharAttr();
  399.       break;
  400.     case rtfPictAttr:
  401.       fprintf(stderr,"%s: You shouldn't see rtfPictAttr: minor %d\n",
  402.     progname,rtfMinor);
  403.       break;
  404.     case rtfFieldAttr:
  405.       FieldAttr();
  406.       break;
  407.     case rtfTOCAttr:
  408.       TOCAttr();
  409.       break;
  410.     case rtfPosAttr:
  411.       PosAttr();
  412.       break;
  413.    }
  414. }
  415. /*****************************************************************************
  416.  *
  417.  * Control class major number handlers.  Each one switches on the
  418.  * minor numbers that occur within the major number.  rtfStyleSheet,
  419.  * rtfFontTbl, and rtfColorTbl are not in the switch because they're
  420.  * handled by the reader. rtfPict has its own callback.
  421.  */
  422. static void
  423. CharSet()
  424. {
  425.    switch (rtfMinor) {
  426.     case rtfAnsiCharSet:
  427.       break;
  428.     case rtfMacCharSet:
  429.       break;
  430.     case rtfPcCharSet:
  431.       break;
  432.     case rtfPcaCharSet:
  433.       break;
  434.    }
  435. }
  436. static void
  437. Destination()
  438. {
  439.    switch (rtfMinor) {
  440.     case rtfFootnote:
  441.       output_str("%\n",'\0');
  442.       output_str("\\footnote{",'\0');
  443.       push_LaTeX_stack("}%\n",Footnote,0);
  444.       break;
  445.     case rtfHeader:
  446.       if (!initialised)
  447.     initialise();
  448.       if (header_on)
  449.     {
  450.     output_str("\\markright{",'\0');
  451.     push_LaTeX_stack(" }\n",Header,0);
  452.     }
  453.       else
  454.     {
  455.     RTFSkipGroup();
  456.     RTFUngetToken();
  457.     }
  458.       break;
  459.     case rtfHeaderLeft:
  460.     case rtfHeaderRight:
  461.     case rtfHeaderFirst:
  462.       if (verbose)
  463.      msg_not_supported(rtfTextBuf+1);
  464.       break;
  465.     case rtfFooter:
  466.       if (header_on)
  467.     {
  468.     if (verbose)
  469.         fprintf(stderr,"LaTeX  supports only the header\n");
  470.     output_str("% LaTeX  supports only the header\n",'\0');
  471.     }
  472.     RTFSkipGroup();
  473.     RTFUngetToken();
  474.       break;
  475.     case rtfFooterLeft:
  476.       break;
  477.     case rtfFooterRight:
  478.       break;
  479.     case rtfFooterFirst:
  480.       break;
  481.     case rtfFNSep:
  482.       break;
  483.     case rtfFNContSep:
  484.       break;
  485.     case rtfFNContNotice:
  486.       break;
  487.     case rtfInfo:
  488.       break;
  489.     case rtfField:
  490.       break;
  491.     case rtfFieldInst:
  492.       {
  493.       char buf[80];
  494.       buf[0]='\0';
  495.       (void)RTFGetToken();
  496.       while(rtfClass==rtfText)
  497.     {
  498.     strcat(buf,rtfTextBuf);
  499.     (void)RTFGetToken();
  500.     }
  501.       RTFUngetToken();
  502.       if (strncmp(buf,"date",4)==0)
  503.     output_str("\\today",'\0');
  504.       else
  505.     if (verbose)
  506.        {
  507.        char msg_buf[80];
  508.        strcpy(msg_buf,rtfTextBuf+1);
  509.        strcat(msg_buf,buf);
  510.        msg_not_yet(msg_buf);
  511.        }
  512.       break;
  513.       }
  514.     break;
  515.     case rtfFieldResult:
  516.       break;
  517.     case rtfIndex:
  518.       break;
  519.     case rtfIndexBold:
  520.       break;
  521.     case rtfIndexItalic:
  522.       break;
  523.     case rtfIndexText:
  524.       break;
  525.     case rtfIndexRange:
  526.       break;
  527.     case rtfTOC:
  528.       break;
  529.     case rtfBookmarkStart:
  530.       break;
  531.     case rtfBookmarkEnd:
  532.       break;
  533.     case rtfITitle:
  534.     (void) RTFGetToken ();
  535.     while (rtfClass == rtfText)
  536.         (void) RTFGetToken ();
  537.     RTFUngetToken();
  538.       break;
  539.     case rtfISubject:
  540.     (void) RTFGetToken ();
  541.     while (rtfClass == rtfText)
  542.         (void) RTFGetToken ();
  543.     RTFUngetToken();
  544.        break;
  545.     case rtfIAuthor:
  546.     (void) RTFGetToken ();
  547.     while (rtfClass == rtfText)
  548.         (void) RTFGetToken ();
  549.     RTFUngetToken();
  550.       break;
  551.     case rtfIOperator:
  552.       break;
  553.     case rtfIKeywords:
  554.     (void) RTFGetToken ();
  555.     while (rtfClass == rtfText)
  556.         (void) RTFGetToken ();
  557.     RTFUngetToken();
  558.       break;
  559.     case rtfIComment:
  560.     (void) RTFGetToken ();
  561.     while (rtfClass == rtfText)
  562.         (void) RTFGetToken ();
  563.     RTFUngetToken();
  564.       break;
  565.     case rtfIVersion:
  566.       break;
  567.     case rtfIVerscomm:
  568. /* \verscomm is a token, made by Macintosh's WORD.
  569.  * I don't know the meaning,
  570.  * because it isn't specified in the RTF-specification.
  571.  */
  572.        RTFSkipGroup();
  573.        RTFUngetToken();
  574.        break;
  575.     case rtfIDoccomm:
  576.     (void) RTFGetToken ();
  577.     while (rtfClass == rtfText)
  578.         (void) RTFGetToken ();
  579.     RTFUngetToken();
  580.       break;
  581.    }
  582. }
  583. static void
  584. SpecialChar()
  585. {
  586.    switch (rtfMinor) {
  587.     case rtfCurHeadPage:
  588.       if (verbose && header_on)
  589.     fprintf(stderr,"LaTeX always puts the page number in right corner\n");
  590.       break;
  591.     case rtfCurFNote:
  592.       {
  593.       static int count=0;
  594.       if (verbose && count++ == 0)
  595.     msg_not_needed(rtfTextBuf+1);
  596.       break;
  597.       }
  598.     case rtfCurHeadPict:
  599.       msg_not_supported("chpict");
  600.       break;
  601.     case rtfCurHeadDate:
  602.     case rtfCurHeadTime:
  603.       if (verbose)
  604.      msg_not_supported(rtfTextBuf+1);
  605.       break;
  606.     case rtfFormula:
  607.       msg_not_yet("|");
  608.       break;
  609.     case rtfNoBrkSpace:
  610.       if(!text_out) start_para();
  611.       output_str("~",'\0');
  612.       break;
  613.     case rtfNoReqHyphen:
  614.       output_str("\\-",'\0');
  615.       break;
  616.     case rtfNoBrkHyphen:
  617.       if(!text_out) start_para();
  618.       output('-',1);
  619.       break;
  620.     case rtfPage:
  621.       end_para();
  622.       end_table();            /* if there is a table */
  623.       output_str("\n\\newpage\n",'\0');
  624.       break;
  625.     case rtfLine:
  626.       if (!other_linebreak)
  627.     output_str("\\\\ \n",'\0');
  628.       else
  629.           output_str(" \\hfill \\break \n",'\0');
  630.       break;
  631.     case rtfPar:
  632.       if (top_LaTeX_flags(Header))
  633.       {
  634.           if (!other_linebreak)
  635.           output_str("\\\\ \n",'\0');
  636.           else
  637.           output_str(" \\hfill \\break \n",'\0');
  638.       return;
  639.       }
  640.       if (top_LaTeX_flags(SpecialWORDstyle))
  641.       pop_LaTeX_stack();
  642.       if (tab==2 && text_out)
  643.       {
  644.       while (!top_LaTeX_flags(Tabstops) )
  645.          if (pop_LaTeX_stack()==0) break;
  646.       rtf_current=rtf_default;
  647.       output_str("\\\\ \n",'\0');
  648.       update_current();
  649.       }
  650.                         /* we may want to deal with this
  651.                        elsewhere, so as to pop the stacks
  652.                        before printing the newline */
  653.       RTFGetToken();
  654.       if(RTFCheckCM(rtfGroup,rtfEndGroup) ||
  655.      RTFCheckCMM(rtfControl,rtfParAttr,rtfParDef)) {
  656.      end_of_par = 1;
  657. /* Don't know if this one is needed anymore
  658.  *      } else if(in_table && RTFCheckCMM(rtfControl,rtfSpecialChar,rtfPar)) {
  659.  *     end_table();            * two \par's in a row *
  660.  */
  661.       } else {
  662.      end_para();
  663.       }
  664.       RTFUngetToken();
  665.       break;
  666.     case rtfSect:
  667.       rtfMinor = rtfPar;        /* pretend that it's just a para */
  668.       RTFUngetToken();
  669.       break;
  670.     case rtfTab:
  671.       if (top_LaTeX_flags(SpecialWORDstyle)) 
  672.     return;                /* no tab stops in header, haeding, ...*/
  673.       if(!text_out) start_para();
  674.       if (!tabstops_on)
  675.     break;
  676.       if (tab)
  677.      {
  678.      while (!top_LaTeX_flags(Tabstops) )
  679.         if (pop_LaTeX_stack()==0) break;
  680.      rtf_current=rtf_default;
  681.      output_str("\\> ",'\0');
  682.      update_current();
  683.      }
  684.       else
  685.      {
  686.      output(' ',1);
  687.      if (verbose && tabstops_on)
  688.         fprintf(stderr,"this tab stop is ignored\n   you have to specify the position of the tab stop before\n");
  689.      }
  690.       break;
  691.     case rtfCell:
  692.       while (!top_LaTeX_flags(Tabular) )
  693.     if (pop_LaTeX_stack()==0) break;
  694.       rtf_current=rtf_default;
  695.       cellnr++;
  696.       if (cellnr<max_cellnr)
  697.           output_str(" & ",'\0');
  698.       update_current();
  699.       break;
  700.     case rtfRow:
  701.       while (!top_LaTeX_flags(Tabular) )
  702.     if (pop_LaTeX_stack()==0) break;
  703.       rtf_current=rtf_default;
  704.       cellnr=0;
  705.       output_str("\\\\",'\0');
  706.       output('\n',1);
  707.       update_current();
  708.       break;
  709.     case rtfCurAnnot:
  710.       break;
  711.     case rtfAnnotation:
  712.       break;
  713.     case rtfAnnotID:
  714.       break;
  715.     case rtfCurAnnotRef:
  716.       break;
  717.     case rtfFNoteSep:
  718.       break;
  719.     case rtfFNoteCont:
  720.       break;
  721.     case rtfColumn:
  722.       break;
  723.     case rtfOptDest:
  724.       break;
  725.     case rtfIIntVersion:
  726.       break;
  727.     case rtfICreateTime:
  728.       break;
  729.     case rtfIRevisionTime:
  730.       break;
  731.     case rtfIPrintTime:
  732.       break;
  733.     case rtfIBackupTime:
  734.       break;
  735.     case rtfIEditTime:
  736.       break;
  737.     case rtfIYear:
  738.       break;
  739.     case rtfIMonth:
  740.       break;
  741.     case rtfIDay:
  742.       break;
  743.     case rtfIHour:
  744.       break;
  745.     case rtfIMinute:
  746.       break;
  747.     case rtfINPages:
  748.       break;
  749.     case rtfINWords:
  750.       break;
  751.     case rtfINChars:
  752.       break;
  753.     case rtfIIntID:
  754.       break;
  755.     case rtfBullet:
  756.       output_str("\\bullet ",'\0');
  757.       break;
  758.     case rtfEmDash:
  759.       output_str("---",'\0');
  760.       break;
  761.     case rtfEnDash:
  762.       output_str("--",'\0');
  763.       break;
  764.     case rtfLQuote:
  765.       if(german_squotes)
  766.      output_str("\\glq ",'\0');
  767.       else
  768.      output_str("`",'\0');
  769.       break;
  770.     case rtfRQuote:
  771.       if(german_squotes)
  772.      output_str("\\grq ",'\0');
  773.       else
  774.      output_str("'",'\0');
  775.       break;
  776.     case rtfLDblQuote:
  777.       if(german_dquotes)
  778.      output_str("\"`",'\0');
  779.       else
  780.      output_str("``",'\0');
  781.       break;
  782.     case rtfRDblQuote:
  783.       if(german_dquotes)
  784.      output_str("\"'",'\0');
  785.       else
  786.      output_str("''",'\0');
  787.       break;
  788.    }
  789. }
  790. static void
  791. DocAttr()
  792. {
  793.    switch (rtfMinor) {
  794.     case rtfPaperWidth:
  795.     case rtfPaperHeight:
  796.     case rtfLeftMargin:
  797.     case rtfRightMargin:
  798.     case rtfTopMargin:
  799.     case rtfBottomMargin:
  800.       {
  801.       static int count = 0;
  802.  
  803.       if(verbose > 1 || (verbose && count++ == 0)) {
  804.            msg_not_yet(rtfTextBuf+1);
  805.         }
  806.        }
  807.       break;
  808.     case rtfFacingPage:
  809.       if(verbose)
  810.            msg_not_yet(rtfTextBuf+1);
  811.        break;
  812.     case rtfGutterWid:
  813.       msg_not_yet("gutter");
  814.       break;
  815.     case rtfDefTab:
  816.       msg_not_yet("deftab");
  817.       break;
  818.     case rtfWidowCtrl:
  819.       msg_not_yet("widowctrl");
  820.       break;
  821.     case rtfFNoteEndSect:
  822.       msg_not_yet("endnotes");
  823.       break;
  824.     case rtfFNoteEndDoc:
  825.       break;
  826.     case rtfFNoteBottom:
  827.       break;
  828.     case rtfFNoteText:
  829.       msg_not_yet("ftntj");
  830.       break;
  831.     case rtfFNoteStart:
  832.       if(footnote_num0 != rtfParam) {
  833.      footnote_num0 = rtfParam;
  834.      change_headfoot = 1;
  835.       }
  836.       break;
  837.     case rtfFNoteRestart:
  838.       if(footnotes_restart_each_page != 1) {
  839.      footnotes_restart_each_page = 1;
  840.      change_headfoot = 1;
  841.       }
  842.       break;
  843.     case rtfHyphHotZone:
  844.       break;
  845.     case rtfPageStart:
  846.       pageno = rtfParam;
  847.       break;
  848.     case rtfLineStart:
  849.       lineno = rtfParam;
  850.       break;
  851.     case rtfLandscape:
  852.       msg_not_supported("landscape");
  853.       break;
  854.     case rtfFracWidth:
  855.       break;
  856.     case rtfNextFile:
  857.       break;
  858.     case rtfTemplate:
  859.       break;
  860.     case rtfMakeBackup:
  861.       break;
  862.     case rtfRTFDefault:
  863.       break;
  864.     case rtfRevisions:
  865.       break;
  866.     case rtfMirrorMargin:
  867.       break;
  868.     case rtfRevDisplay:
  869.       break;
  870.     case rtfRevBar:
  871.       break;
  872.    }
  873. }
  874. /*****************************************************************************/
  875.  
  876. static void
  877. SectAttr()
  878. {
  879.    switch (rtfMinor) {
  880.     case rtfSectDef:
  881.       set_headfoot_lines();
  882.       break;
  883.     case rtfNoBreak:
  884.       break;
  885.     case rtfColBreak:
  886.       break;
  887.     case rtfPageBreak:
  888.       break;
  889.     case rtfEvenBreak:
  890.       break;
  891.     case rtfOddBreak:
  892.       break;
  893.     case rtfPageStarts:
  894.       break;
  895.     case rtfPageCont:
  896.       break;
  897.     case rtfPageRestart:
  898.       break;
  899.     case rtfPageDecimal:
  900.       if(pageno_style != Pageno_Decimal) {
  901.      pageno_style = Pageno_Decimal;
  902.      change_headfoot = 1;
  903.       }
  904.       break;
  905.     case rtfPageURoman:
  906.       if(pageno_style != Pageno_URoman) {
  907.      pageno_style = Pageno_URoman;
  908.      change_headfoot = 1;
  909.       }
  910.       break;
  911.     case rtfPageLRoman:
  912.       if(pageno_style != Pageno_LRoman) {
  913.      pageno_style = Pageno_LRoman;
  914.      change_headfoot = 1;
  915.       }
  916.       break;
  917.     case rtfPageULetter:
  918.       msg_not_yet("pgnucltr");
  919.       break;
  920.     case rtfPageLLetter:
  921.       msg_not_yet("pgnlcltr");
  922.       break;
  923.     case rtfPageNumLeft:
  924.       if(pageno_x != rtfParam) {
  925.      pageno_x = rtfParam;
  926.      change_headfoot = 1;
  927.       }
  928.       break;
  929.     case rtfPageNumTop:
  930.       if(pageno_y != rtfParam) {
  931.      pageno_y = rtfParam;
  932.      change_headfoot = 1;
  933.       }
  934.       break;
  935.     case rtfLineModulus:
  936.       if(rtfParam != 0) msg_not_supported("linemod");
  937.       break;
  938.     case rtfLineStarts:
  939.       break;
  940.     case rtfLineDist:
  941.       msg_not_supported("linex");
  942.       break;
  943.     case rtfLineRestart:
  944.       msg_not_supported("linerestart");
  945.       break;
  946.     case rtfLineRestartPg:
  947.       msg_not_supported("lineppage");
  948.       break;
  949.     case rtfLineCont:
  950.       msg_not_supported("linecont");
  951.       break;
  952.     case rtfHeaderY:
  953.       msg_not_yet("headery");
  954.       break;
  955.     case rtfFooterY:
  956.       msg_not_yet("footery");
  957.       break;
  958.     case rtfTopVAlign:
  959.       break;
  960.     case rtfBottomVAlign:
  961.       break;
  962.     case rtfCenterVAlign:
  963.       break;
  964.     case rtfJustVAlign:
  965.       break;
  966.     case rtfColumns:
  967.       if(rtfParam != 1) msg_not_yet("cols");
  968.       break;
  969.     case rtfColumnLine:
  970.       break;
  971.     case rtfColumnSpace:
  972.       msg_not_yet("colsx");
  973.       break;
  974.     case rtfENoteHere:
  975.       msg_not_supported("endnhere");
  976.       break;
  977.     case rtfTitleSpecial:
  978.       msg_not_supported("titlepg");
  979.       break;
  980.    }
  981. }
  982. static void 
  983. TblAttr()
  984. {
  985.    switch (rtfMinor) {
  986.     case rtfCellBordBottom:
  987.     case rtfCellBordTop:
  988.     case rtfCellBordLeft:
  989.     case rtfCellBordRight:
  990.       {
  991.       static int count = 0;
  992.  
  993.       if(verbose > 1 || (verbose && count++ == 0)) {
  994.            msg_not_yet(rtfTextBuf+1);
  995.         }
  996.        }
  997.       break;
  998.     case rtfRowDef:
  999.       table_mode=1;
  1000.       push_LaTeX_stack("",TabularInit,1);
  1001.       strcpy(tabinitnew,"\n\\begin{tabular}{");
  1002.       endOfLastCell=-70;
  1003.       max_cellnr=0;
  1004.       break;
  1005.     case rtfRowLeft:
  1006.     case rtfRowRight:
  1007.     case rtfRowCenter:
  1008.     case rtfRowGapH:
  1009.     case rtfRowHt:
  1010.     case rtfRowLeftEdge:
  1011.       {
  1012.       static int count = 0;
  1013.  
  1014.       if(verbose > 1 || (verbose && count++ == 0)) {
  1015.            msg_not_yet(rtfTextBuf+1);
  1016.         }
  1017.        }
  1018.       break;
  1019.     case rtfCellPos:
  1020.       {
  1021.       unsigned int cell_bright;
  1022.  
  1023.       max_cellnr++;
  1024.       cell_bright=(rtfParam-endOfLastCell)*smaller_cell_factor;
  1025.       sprintf(buff,"p{%gpt}",TW_TO_PT(cell_bright));
  1026.       strcat(tabinitnew,buff);
  1027.       endOfLastCell=rtfParam;
  1028.       break;
  1029.       }
  1030.     case rtfCellShading:
  1031. /* \clshdng is a token, made by Macintosh's WORD
  1032.  * I don't know the meaning,
  1033.  * because it isn't specified in the RTF-specification
  1034.  */
  1035.       break;
  1036.     case rtfMergeRngFirst:
  1037.       break;
  1038.     case rtfMergePrevious:
  1039.       break;
  1040.    }
  1041. }
  1042. /*****************************************************************************/
  1043. static void
  1044. ParAttr()
  1045. {
  1046.    switch (rtfMinor) {
  1047.     case rtfParDef:
  1048.       if(!initialised) {        /* it's hard to know where to call it*/
  1049.      initialise();
  1050.       }
  1051.       while(top_LaTeX_flags(Font) || top_LaTeX_flags(Font_Num) ||
  1052.         top_LaTeX_flags(Font_Size) || top_LaTeX_flags(Style) ||
  1053.         top_LaTeX_flags(Undefined) || top_LaTeX_flags(Underline) ||
  1054.         top_LaTeX_flags(Sub_Super) || 
  1055.         top_LaTeX_flags(Paragraph) ||
  1056.         top_LaTeX_flags(NormalWORDstyle) ||
  1057.         top_LaTeX_flags(LRskip) || top_LaTeX_flags(SpecialWORDstyle)) {
  1058.      (void)pop_LaTeX_stack();
  1059.       }
  1060.       rtf_current.par_attr.leftskip=rtf_current.par_attr.rightskip=0;
  1061.       if (top_LaTeX_flags(Tabstops))
  1062.     {
  1063.      (void)pop_LaTeX_stack();
  1064.     Cformatting_char=formatting_char;
  1065.     Cformatting_para=formatting_para;
  1066.     }
  1067.       if (!table_mode && top_LaTeX_flags(Tabular))
  1068.     end_table();                  /* it's hard to know where to call it*/
  1069.       if ((table_mode) &&               /* begin of a table in rtf */
  1070.         top_LaTeX_flags(TabularInit)  )
  1071.      if (strcmp(tabinitold,tabinitnew)==0)
  1072.         {                          /*we haven't finished the last */
  1073.         (void)pop_LaTeX_stack();   /* table in LaTeX and the parameters */
  1074.         }                          /* of both the current and last      */
  1075.                        /* rtf-table are equal so we needn't */
  1076.                        /* start a new LaTeX-table      */
  1077.      else
  1078.         {
  1079.         end_table();         /* we will have to finish the last table, if there is one  */
  1080.         strcpy(tabinitold,tabinitnew);
  1081.         table_mode=1;
  1082.         output_str(tabinitnew,'\0'); /* and to start a new one */
  1083.         output_str("}\n",'\0');
  1084.         push_LaTeX_stack("\\end{tabular}\n",Tabular,0);
  1085.         Cformatting_char=formatting_char&&formatting_table;
  1086.         Cformatting_para=formatting_para&&formatting_table;
  1087.         }
  1088.       if(end_of_par /*&& !table_mode*/) {
  1089.      end_para();
  1090.       }
  1091.       ntabs = 0;
  1092.       table_mode=0;
  1093.       tab=0;
  1094.       rtf_default.LaTeX_stack = rtf_ptr->LaTeX_stack;
  1095.       rtf_default.prev = rtf_ptr->prev;
  1096.       *rtf_ptr = rtf_default;
  1097.       rtf_current.char_attr = rtf_default.char_attr;
  1098.       (void)RTFSetClassCallback(rtfText, start_para); /* not really start a new pragraph
  1099.                              but have a look if there is a 
  1100.                              table end */
  1101.       break;
  1102.     case rtfStyleNum:
  1103.       if(inDefineStyle)
  1104.      RTFExpandStyle(rtfParam);
  1105.       else
  1106.      {
  1107.      if(!initialised)
  1108.          {        /* it's hard to know where to call it*/
  1109.  
  1110.          RTFUngetToken();   /* store the Token, because initialise  */
  1111.          initialise();      /* changes it                           */
  1112.          RTFGetToken();
  1113.          }
  1114.      if (!table_mode && top_LaTeX_flags(Tabular))
  1115.         end_table();                  /* it's hard to know where to call it*/
  1116.      setstylecommand(rtfParam);
  1117.      }
  1118.       break;
  1119.     case rtfQuadLeft:
  1120.       {
  1121.      static int count = 0;
  1122.      
  1123.      if(verbose > 1 || (verbose && count++ == 0)) {
  1124.         msg_map_to("gl","gj");
  1125.      }
  1126.      rtf_ptr->par_attr.flags |= LeftAlign;
  1127.       }
  1128.       break;
  1129.     case rtfQuadRight:
  1130.       if (text_out)
  1131.     {
  1132.         if (!Cformatting_para)                /* no paragraph formatting */
  1133.         break;
  1134.     output_str("\n\\begin{flushright}",'\0');
  1135.     push_LaTeX_stack("\n\\end{flushright}",Paragraph,0);
  1136.     }
  1137.       else
  1138.     rtf_ptr->par_attr.flags |= RightAlign;
  1139.       break;
  1140.     case rtfQuadJust:
  1141.       rtf_ptr->par_attr.flags &= ~(LeftAlign | Centred | RightAlign);
  1142.       break;
  1143.     case rtfQuadCenter:
  1144.       if (text_out)
  1145.     {
  1146.         if (!Cformatting_para)                /* no paragraph formatting */
  1147.         break;
  1148.     output_str("\n\\begin{center}",'\0');
  1149.     push_LaTeX_stack("\n\\end{center}",Paragraph,0);
  1150.     }
  1151.       else
  1152.     rtf_ptr->par_attr.flags |= Centred;
  1153.       break;
  1154.     case rtfFirstIndent:
  1155.       rtf_ptr->par_attr.parindent = rtfParam;
  1156.       break;
  1157.     case rtfLeftIndent:
  1158.       rtf_ptr->par_attr.leftskip = rtfParam;
  1159.       break;
  1160.     case rtfRightIndent:
  1161.       rtf_ptr->par_attr.rightskip = rtfParam;
  1162.       break;
  1163.     case rtfSpaceBefore:
  1164.       rtf_ptr->par_attr.skip_before = rtfParam;
  1165.       break;
  1166.     case rtfSpaceAfter:
  1167.       rtf_ptr->par_attr.skip_after = rtfParam;
  1168.       break;
  1169.     case rtfSpaceBetween:
  1170.       break;
  1171.     case rtfInTable:
  1172.       table_mode=1;
  1173.       break;
  1174.     case rtfKeep:
  1175.       break;
  1176.     case rtfKeepNext:
  1177.       break;
  1178.     case rtfSideBySide:
  1179.       break;
  1180.     case rtfPBBefore:
  1181.       break;
  1182.     case rtfNoLineNum:            /* ignored */
  1183.       break;
  1184.     case rtfBorderTop:
  1185.       break;
  1186.     case rtfBorderBottom:
  1187.       break;
  1188.     case rtfBorderLeft:
  1189.       break;
  1190.     case rtfBorderRight:
  1191.       break;
  1192.     case rtfBorderBar:
  1193.       break;
  1194.     case rtfBorderBox:
  1195.       break;
  1196.     case rtfBorderBetween:
  1197.       break;
  1198.     case rtfBorderSingle:
  1199.       break;
  1200.     case rtfBorderThick:
  1201.       break;
  1202.     case rtfBorderShadow:
  1203.       break;
  1204.     case rtfBorderDouble:
  1205.       break;
  1206.     case rtfBorderDot:
  1207.       break;
  1208.     case rtfBorderHair:
  1209.       break;
  1210.     case rtfBorderSpace:
  1211.       break;
  1212.     case rtfTabPos:
  1213.       if (top_LaTeX_flags(SpecialWORDstyle))
  1214.     return;                /*no tab stops in header, heading, ...*/
  1215.       if (!tabstops_on)
  1216.     break;
  1217.       if (!table_mode && top_LaTeX_flags(Tabular))
  1218.     end_table();
  1219.       if (table_mode)
  1220.     {
  1221.     if (verbose)
  1222.         fprintf(stderr,"can't deal with tab stops in tables");
  1223.     }
  1224.       else
  1225.     {
  1226.     tab=1;
  1227.     if(ntabs >= NTABS) {
  1228.         if(ntabs == NTABS)
  1229.             fprintf(stderr,"%s: Attempt to set more than %d tabs\n",
  1230.                 progname,NTABS);
  1231.     } else {
  1232.         tabstops[ntabs++].pos = rtfParam;
  1233.         tabstops[ntabs].type = TabLeft;
  1234.     }
  1235.       }
  1236.       break;
  1237.     case rtfTabRight:
  1238.       if(ntabs < NTABS) {
  1239.      tabstops[ntabs].type = TabRight;
  1240.       }
  1241.       break;
  1242.     case rtfTabCenter:
  1243.       if(ntabs < NTABS) {
  1244.      tabstops[ntabs].type = TabCentre;
  1245.       }
  1246.       break;
  1247.     case rtfTabDecimal:
  1248.       if(ntabs < NTABS) {
  1249.      tabstops[ntabs].type = TabDecimal;
  1250.       }
  1251.       break;
  1252.     case rtfTabBar:
  1253.       {
  1254.      static int count = 0;
  1255.      
  1256.      if(verbose > 1 || (verbose && count++ == 0))
  1257.        msg_not_yet("tb");
  1258.       }
  1259.       break;
  1260.     case rtfLeaderDot:
  1261.       break;
  1262.     case rtfLeaderHyphen:
  1263.       break;
  1264.     case rtfLeaderUnder:
  1265.       break;
  1266.     case rtfLeaderThick:
  1267.       break;
  1268.    }
  1269. }
  1270. /*procedure not needed yet*/
  1271. static void PictAttr ()
  1272. {
  1273.    switch (rtfMinor) {
  1274.     case rtfMacQD:
  1275.       break;
  1276.     case rtfWinMetafile:
  1277.       break;
  1278.     case rtfWinBitmap:
  1279.       break;
  1280.     case rtfPicWid:
  1281.       break;
  1282.     case rtfPicHt:
  1283.       break;
  1284.     case rtfPicGoalWid:
  1285.       break;
  1286.     case rtfPicGoalHt:
  1287.       break;
  1288.     case rtfPicScaleX:
  1289.       break;
  1290.     case rtfPicScaleY:
  1291.       break;
  1292.     case rtfPicScaled:
  1293.       break;
  1294.     case rtfPicCropTop:
  1295.       break;
  1296.     case rtfPicCropBottom:
  1297.       break;
  1298.     case rtfPicCropLeft:
  1299.       break;
  1300.     case rtfPicCropRight:
  1301.       break;
  1302.     case rtfPixelBits:
  1303.       break;
  1304.     case rtfBitmapPlanes:
  1305.       break;
  1306.     case rtfBitmapWid:
  1307.       break;
  1308.     case rtfPicBinary:
  1309.       break;
  1310.    }
  1311. }
  1312. /*****************************************************************************/
  1313. static void
  1314. FieldAttr()
  1315. {
  1316.    switch (rtfMinor) {
  1317.     case rtfFieldDirty:
  1318.       break;
  1319.     case rtfFieldEdited:
  1320.       break;
  1321.     case rtfFieldLocked:
  1322.       break;
  1323.     case rtfFieldPrivate:
  1324.       break;
  1325.    }
  1326. }
  1327. /*****************************************************************************/
  1328. static void
  1329. TOCAttr()
  1330. {
  1331.    switch (rtfMinor) {
  1332.     case rtfTOCType:
  1333.       break;
  1334.     case rtfTOCLevel:
  1335.       break;
  1336.    }
  1337. }
  1338. /*****************************************************************************/
  1339. static void
  1340. PosAttr()
  1341. {
  1342.    switch (rtfMinor) {
  1343.     case rtfPosX:
  1344.       break;
  1345.     case rtfPosXCenter:
  1346.       break;
  1347.     case rtfPosXInside:
  1348.       break;
  1349.     case rtfPosXLeft:
  1350.       break;
  1351.     case rtfPosXOutSide:
  1352.       break;
  1353.     case rtfPosXRight:
  1354.       break;
  1355.     case rtfPosY:
  1356.       break;
  1357.     case rtfPosYInline:
  1358.       break;
  1359.     case rtfPosYTop:
  1360.       break;
  1361.     case rtfPosYCenter:
  1362.       break;
  1363.     case rtfPosYBottom:
  1364.       break;
  1365.     case rtfAbsWid:
  1366.       break;
  1367.     case rtfTextDist:
  1368.       break;
  1369.     case rtfRPosMargV:
  1370.       break;
  1371.     case rtfRPosPageV:
  1372.       break;
  1373.     case rtfRPosMargH:
  1374.       break;
  1375.     case rtfRPosPageH:
  1376.       break;
  1377.     case rtfRPosColH:
  1378.       break;
  1379.    }
  1380. }
  1381. /*****************************************************************************
  1382.  *
  1383.  * Deal with Pict destinations
  1384.  */
  1385. static void
  1386. read_pict()
  1387. {
  1388. static int count=0;
  1389. if (verbose && count++==0)
  1390.     fprintf(stderr,"%s: Don't support any picture-things yet; be patient\n",
  1391.     progname);
  1392. if (verbose>1)
  1393.     msg_not_yet(rtfTextBuf+1);
  1394.     RTFSkipGroup ();
  1395.     RTFRouteToken ();       /* feed "}" back to router */
  1396.  
  1397. }
  1398. /*****************************************************************************
  1399.  *
  1400.  * Deal with things like footnote numbering and page numbers; things
  1401.  * that involve the headline or footline
  1402.  */
  1403. static void
  1404. set_headfoot_lines()
  1405. {
  1406.    int pageno_top = (pageno_y < paper_height/2 ? 1 : 0);
  1407.    if(!change_headfoot) return;
  1408. # ifdef notdef /* I think this is left over from rtf2tex */
  1409. /*
  1410.  * The headline first
  1411.  *
  1412.    output_str("\\headline={\\tenrm ",'\0');
  1413.    if(footnotes_restart_each_page) {
  1414.       sprintf(buff,"\\footnum=%d",footnote_num0);
  1415.       output_str(buff,' ');
  1416.  }
  1417.    if(pageno_top) {
  1418.       sprintf(buff,"\\kern %gpt %s\\hfil",TW_TO_PT(pageno_x),page_num());
  1419.       output_str(buff,' ');
  1420.    }
  1421.    output_str("}",'\n');
  1422. /*
  1423.  * And now the foot
  1424.  *
  1425.    output_str("\\footline={\\tenrm ",'\0');
  1426.    if(!pageno_top) {
  1427.       sprintf(buff,"\\kern %gpt %s\\hfil",TW_TO_PT(pageno_x),page_num());
  1428.       output_str(buff,' ');
  1429.    }
  1430.    output_str("}",'\n');
  1431.    change_headfoot = 0;            /* we've done it *
  1432. */
  1433. # endif /* notdef */
  1434. }
  1435. /*****************************************************************************
  1436.  *
  1437.  * Convert the pageno to the desired form
  1438.  */
  1439. static char *
  1440. page_num()
  1441. {
  1442.    switch (pageno_style) {
  1443.     case Pageno_Decimal:
  1444.       return("\\number\\pageno");
  1445.     case Pageno_LRoman:
  1446.       return("\\romannumeral\\pageno");
  1447.     case Pageno_URoman:
  1448.       return("\\uppercase\\expandafter{\\romannumeral\\pageno}");
  1449.     default:
  1450.       return("");
  1451.    }
  1452. }
  1453. /*****************************************************************************
  1454.  *
  1455.  * This is called when we see the first text token after each \par
  1456.  */
  1457. #define CURRENT(WHAT)            /* is WHAT up-to-date? */ \
  1458.    (rtf_current.WHAT == rtf_ptr->WHAT)
  1459. static void
  1460. start_para()
  1461. {
  1462.    if(!initialised) {            /* this could be the place */
  1463.       initialise();
  1464.    }
  1465.  
  1466.    if(!table_mode && top_LaTeX_flags(Tabular))
  1467.         end_table();
  1468.    if (tab==1 && !table_mode)
  1469.     start_tabstops();
  1470.    update_current();
  1471.     text_out = 1;
  1472.     (void)RTFSetClassCallback(rtfText, TextClass);
  1473.     if(rtfClass == rtfText) {
  1474.         RTFUngetToken();            /* re-schedule the text */
  1475.    }
  1476. }
  1477. /*
  1478.  * End a paragraph
  1479.  */
  1480. static void
  1481. end_para()
  1482. {
  1483.    if(in_table) {
  1484.       tab_num = 0;
  1485.    } else {
  1486.       if (top_LaTeX_flags(SpecialWORDstyle) || top_LaTeX_flags(Header))
  1487.     pop_LaTeX_stack();
  1488.       output('\n',1);
  1489.       output('\n',1);
  1490.       }
  1491.    text_out = 0;
  1492.    end_of_par = 0;
  1493.    (void)RTFSetClassCallback(rtfText, start_para);
  1494. }
  1495. /*****************************************************************************
  1496.  *
  1497.  * Force an update of the current state, only emitting commands
  1498.  * that actually change anything.
  1499.  */
  1500. static void
  1501. update_current()
  1502. {
  1503.    RTFStyle *style;
  1504.  
  1505. if (Cformatting_char)
  1506. {
  1507.    if(!CURRENT(char_attr.FontSize))
  1508.       set_fontsize(rtf_ptr->char_attr.FontSize);
  1509.    if(!CURRENT(char_attr.sub_super_height))
  1510.       set_subsuper(rtf_ptr->char_attr.sub_super_height);
  1511.    if(!CURRENT(char_attr.smallcaps))
  1512.       set_smallcaps();
  1513.    if(!CURRENT(char_attr.font))
  1514.    if(rtf_ptr->char_attr.font == Bold) {
  1515.     if (initialised)
  1516.           set_font(Bold,1,"\n{\\bf ","}");
  1517.     else
  1518.           set_font(Bold,1,"\n\\bf ","");
  1519.    }
  1520.    if(!CURRENT(char_attr.font))
  1521.    if(rtf_ptr->char_attr.font == Italic) {
  1522.     if (initialised)
  1523.           set_font(Italic,1,"\n{\\it ","}");
  1524.     else
  1525.           set_font(Italic,1,"\n\\it ","");
  1526.    }
  1527. }
  1528. if (Cformatting_para)
  1529. {
  1530.    if(!CURRENT(par_attr.flags))
  1531.     switch (rtf_ptr->par_attr.flags)
  1532.       {
  1533.       case Centred:
  1534.         output_str("\n\\begin{center}",'\0');
  1535.         push_LaTeX_stack("\n\\end{center}",Paragraph,0);
  1536.         break;
  1537.       case RightAlign:
  1538.         output_str("\n\\begin{flushright}",'\0');
  1539.         push_LaTeX_stack("\n\\end{flushright}",Paragraph,0);
  1540.         break;
  1541.       case LeftAlign:
  1542.         output_str("\n\\begin{flushleft}",'\0');
  1543.         push_LaTeX_stack("\n\\end{flushleft}",Paragraph,0);
  1544.         break;
  1545.       default:                 /* block modus (LaTeX default)*/
  1546.         break;
  1547.   }
  1548.    if(!CURRENT(par_attr.parindent))
  1549.     {
  1550.     if (rtf_ptr->par_attr.parindent==LaTeXdefault)
  1551.         sprintf(buff,"\n\\setlength{\\parindent}{\\defaultparindent}");
  1552.     else
  1553.         sprintf(buff,"\n\\setlength{\\parindent}{%gpt}",
  1554.              TW_TO_PT(rtf_ptr->par_attr.parindent));
  1555.     output_str(buff,'\0');
  1556.     }
  1557.    if (!CURRENT(par_attr.skip_before) ||
  1558.        !CURRENT(par_attr.skip_after))
  1559.     {
  1560.     int skip;
  1561.  
  1562.     skip=rtf_ptr->par_attr.skip_after+rtf_ptr->par_attr.skip_before;
  1563.     sprintf(buff,"\n\\setlength{\\parskip}{%gpt}",
  1564.          TW_TO_PT(skip));
  1565.     output_str(buff,'\0');
  1566.     }
  1567.    if((!CURRENT(par_attr.leftskip) || !CURRENT(par_attr.rightskip)) &&
  1568.        rl_skip_on)
  1569.     {
  1570.     if ((rtf_ptr->par_attr.leftskip!=0) ||
  1571.         (rtf_ptr->par_attr.rightskip!=0) )
  1572.         {
  1573.         output_str("\n\\begin{list}",'\0');
  1574.         output_str("{ }{",'\0');
  1575.         sprintf(buff,"\n\\setlength{\\leftmargin}{%gpt}",
  1576.              TW_TO_PT(rtf_ptr->par_attr.leftskip));
  1577.         output_str(buff,'\0');
  1578.         sprintf(buff,"\\setlength{\\rightmargin}{%gpt}",
  1579.              TW_TO_PT(rtf_ptr->par_attr.rightskip));
  1580.         output_str(buff,'\0');
  1581.         output_str("\n\\setlength{\\topsep}{0pt}",'\0');
  1582.         output_str("\\setlength{\\partopsep}{0pt}",'\0');
  1583.         output_str("}\n\\item ",'\0');
  1584.         push_LaTeX_stack("\n\\end{list}",LRskip,0);
  1585.         }
  1586.     }
  1587.  
  1588. }
  1589.    rtf_current = *rtf_ptr;
  1590.    rtf_current.LaTeX_stack = NULL;
  1591.    rtf_current.prev = NULL;
  1592. }
  1593. /*****************************************************************************
  1594.  *
  1595.  * ALLDONE
  1596.  */
  1597.  
  1598. #define SET_FONT(FONT,START,END)    /* set a Font */\
  1599.   if(text_out && initialised) { \
  1600.      set_font(FONT,(rtfParam == 0 ? 0 : 1),START,END); \
  1601.   } \
  1602.   rtf_ptr->char_attr.font = (rtfParam == 0 ? 0 : FONT);
  1603. #define SET_FONTSIZE(FONTSIZE)    /* set a Fontsize */\
  1604.   if(text_out && initialised) { \
  1605.      set_fontsize(FONTSIZE); \
  1606.   } \
  1607.   rtf_ptr->char_attr.FontSize = FONTSIZE;
  1608.  
  1609.  
  1610. static void
  1611. CharAttr()
  1612. {
  1613.    switch (rtfMinor) {
  1614.     case rtfPlain:
  1615.       if(text_out) {
  1616.          while(top_LaTeX_flags(Underline) || top_LaTeX_flags(Sub_Super)
  1617.         || top_LaTeX_flags(Font) || top_LaTeX_flags(Font_Num))
  1618.         (void)pop_LaTeX_stack();
  1619.       }
  1620.       rtf_ptr->char_attr = rtf_default.char_attr;
  1621.       rtf_current.char_attr = rtf_default.char_attr;
  1622.       break;
  1623.     case rtfBold:
  1624.       SET_FONT(Bold,"\n{\\bf ","}");
  1625.       break;
  1626.     case rtfItalic:
  1627.       SET_FONT(Italic,"\n{\\it ","}");
  1628.       break;
  1629.     case rtfAllCaps:
  1630.        {
  1631.        static int count;
  1632.      if(verbose > 1 || (verbose && count++ == 0)) {
  1633.             msg_map_to("ac","sc");
  1634.          }
  1635.        }
  1636.     case rtfSmallCaps:
  1637.      if(text_out && initialised)
  1638.     set_smallcaps();
  1639.      rtf_ptr->char_attr.smallcaps = 1;
  1640.       break;
  1641.     case rtfStrikeThru:
  1642.     case rtfOutline:
  1643.     case rtfShadow:
  1644.     case rtfInvisible:
  1645.       {
  1646.      static int count = 0;
  1647.      
  1648.      if(verbose > 1 || (verbose && count == 0))
  1649.        msg_not_supported(
  1650.                  rtfMinor == rtfStrikeThru ? "strike" :
  1651.                  rtfMinor == rtfOutline ? "outl" :
  1652.                  rtfMinor == rtfShadow ? "shad" :
  1653.                  rtfMinor == rtfInvisible ? "v" : "Unknown");
  1654.      count++;
  1655.       }
  1656.       break;
  1657.     case rtfFontNum:
  1658.       break;
  1659.     case rtfFontSize:
  1660.       SET_FONTSIZE(rtfParam/2);
  1661.       break;
  1662.     case rtfDbUnderline:
  1663.     case rtfDUnderline:
  1664.       if (!noUnderline)
  1665.       {
  1666.     if (initialised)
  1667.      {
  1668.      output_str("\n\\underline{\\underline{",'\0');
  1669.      push_LaTeX_stack("}}",Underline,0);
  1670.      }
  1671. /*    else         doesn't work in LaTeX
  1672.      {
  1673.      output_str("\n\\underline \\bgroup \\underline \\bgroup",'\0');
  1674.      push_LaTeX_stack("\\egroup \\egroup",Underline,0);
  1675.      }
  1676. */
  1677.     break;
  1678.       }
  1679.     case rtfUnderline:
  1680.     case rtfWUnderline:
  1681.       {
  1682.      static int count = 0;
  1683.      
  1684.      if (!noUnderline)
  1685.      {
  1686.         if (initialised)
  1687.         {
  1688.         output_str("\n\\underline{",'\0');
  1689.         push_LaTeX_stack("}",Underline,0);
  1690.         }
  1691. /*        else     doesn't work in LaTeX
  1692.         {
  1693.         output_str("\n\\underline \\bgroup",'\0');
  1694.         push_LaTeX_stack("\\egroup",Underline,0);
  1695.         }
  1696. */
  1697.      }
  1698.      else
  1699.      {
  1700.          if(verbose > 1 || (verbose && count++ == 0)) {
  1701.             msg_map_to((rtfMinor == rtfUnderline ? "ul" : "ulw"),"i");
  1702.          }
  1703.         rtfMinor = rtfItalic;
  1704.         CharAttr();
  1705.      }
  1706.       }
  1707.       break;
  1708.     case rtfNoUnderline:
  1709.       break;
  1710.     case rtfSubScript:
  1711.     case rtfSuperScript:
  1712.       if(rtf_ptr->char_attr.sub_super_height == rtfParam) break;
  1713.       if(!text_out && initialised) start_para();
  1714.   if(text_out && initialised) {
  1715.      set_subsuper(rtfParam);
  1716.   }
  1717.   rtf_ptr->char_attr.sub_super_height = rtfParam;
  1718.   break;
  1719.     case rtfForeColor:
  1720.       msg_not_supported("cf");
  1721.       break;
  1722.     case rtfBackColor:
  1723.       break;
  1724.     case rtfExpand:
  1725.       msg_not_needed("expnd");
  1726.       break;
  1727.     case rtfRevised:
  1728.       break;
  1729.    }
  1730. }
  1731.  
  1732. /*****************************************************************************
  1733.  *
  1734.  * Various ways of refusing to deal with a keyword
  1735.  *
  1736.  *
  1737.  * Treat \from as \to (e.g. treat \ul as \i)
  1738.  */
  1739. static void
  1740. msg_map_to(from,to)
  1741. char *from, *to;
  1742. {
  1743.    if(verbose && !writing_defs) {
  1744.       fprintf(stderr,"I'm going to treat \\%s as \\%s\n",from,to);
  1745.    }
  1746. }
  1747. /*
  1748.  * Keyword is neither needed by LaTeX or supported by rtf2LaTeX
  1749.  * For example, \expnd to fiddle with inter-character spacing.
  1750.  */
  1751.  
  1752. static void
  1753. msg_not_needed(name)
  1754. char *name;
  1755. {
  1756.    if(verbose && !writing_defs) {
  1757.       fprintf(stderr,"\\%s is neither needed nor supported\n",name);
  1758.    }
  1759. }
  1760. /*
  1761.  * Keyword isn't supported, and probably can't be
  1762.  * For example, \cf to change colours
  1763.  */
  1764. static void
  1765. msg_not_supported(name)
  1766. char *name;
  1767. {
  1768.    static int pointer = 0;
  1769.    for (pointer=0;(name[pointer]!='\0' && isalpha(name[pointer]));pointer++)
  1770.       continue;
  1771.    /* Should fix problem writing to string constants with gcc */
  1772.    if(name[pointer] != '\0')
  1773.       name[pointer]='\0';         /*No argument will be printed*/
  1774.    if(verbose && !writing_defs) {
  1775.       fprintf(stderr,"%s: Don't support \\%s; sorry\n",progname,name);
  1776.    }
  1777. }
  1778. /*
  1779.  * Keyword will be supported, but I haven't done it yet
  1780.  */
  1781. static void
  1782. msg_not_yet(name)
  1783. char *name;
  1784. {
  1785.    if(verbose && !writing_defs) {
  1786.       fprintf(stderr,"%s: Don't support \\%s yet; be patient\n",progname,name);
  1787.    }
  1788. }
  1789.  
  1790.  
  1791.  
  1792.  
  1793. /*****************************************************************************
  1794.  *
  1795.  * Convert a string to a form that LaTeX can handle
  1796.  *
  1797.  * Remove spaces and capitalise the following letter, 
  1798.  * and converted digits to letters (1 --> A etc., 0 --> O)
  1799.  */
  1800. static char *
  1801. LaTeX_name(str)
  1802. char *str;
  1803. {
  1804.    static char temp[50];
  1805.    char *ptr;
  1806.  
  1807.    for(ptr = temp;*str != '\0';str++) {
  1808.       if(isspace(*str)) {
  1809.      for(str++;isspace(*str);str++) continue;
  1810.      if(*str == '\0') break;
  1811.      *str = islower(*str) ? toupper(*str) : *str;
  1812.      str--; continue;        /* reprocess the character */
  1813.       } else if(isdigit(*str)) {
  1814.      if(*str == '0') *ptr++ = 'O';
  1815.      else *ptr++ = *str + 'A' - '1';
  1816.       } else {
  1817.      *ptr++ = *str;
  1818.       }
  1819.    }
  1820.    *ptr = '\0';
  1821.  
  1822.    return(temp);
  1823. }
  1824.  
  1825. /*****************************************************************************/
  1826.  
  1827. static void
  1828. usage()
  1829. {
  1830.    static char *msg[] = {
  1831.       "Your options are:",
  1832.       "       -c      No character formatting stuff",
  1833.       "       -C file Use another translation-file for characters above 128",
  1834.       "       -d      Use WORD formates within special WORD styles ",
  1835.       "               like heading, footnote text, ...",
  1836.       "       -H      Use LaTeX header and footer, not as default WORD header",
  1837.       "       -h      This message",
  1838.       "       -L file Use another translation-file for specilal WORD styles",
  1839.       "               like heading, footer, footnote text, ...",
  1840.       "       -n      Use \\hfill instead of \\\\ for making a new line",
  1841.       "       -p      No paragraph formatting stuff",
  1842.       "       -r      No left or right skip",
  1843.       "       -s      No tab stops",
  1844.       "       -t      No formatting in tables",
  1845.       "       -T f    Decrease-factor for the cell-width (default:0.7)",
  1846.       "       -u      Change underline to italic",
  1847.       "       -v[#]   Turn on verbose messages; the higher #, the more messages",
  1848.       "       -V      Print the version number",
  1849.       "If you omit the filename rtf2LaTeX will read standard input.",
  1850.       "\nIf there are any LaTeX errors or warnings,",
  1851.       "have a look in the man page section troubleshooting.\n ",
  1852.       NULL,
  1853.    };
  1854.  
  1855.    fprintf(stderr, "Usage: %s [options] [RTF-file]\n", progname);
  1856.    print_text(msg,stderr);
  1857. }
  1858.  
  1859. /*****************************************************************************
  1860.  *
  1861.  * print some text MSG to a stream FIL
  1862.  */
  1863. static void
  1864. print_text(msg,fil)
  1865. char *msg[];
  1866. FILE *fil;
  1867. {
  1868.    char **line;
  1869.  
  1870.    for(line = msg;*line != NULL;line++) {
  1871.       fprintf(fil,"%s\n",*line);
  1872.    }
  1873. }
  1874.  
  1875. /*****************************************************************************
  1876.  *
  1877.  * set a Font
  1878.  */
  1879. static void
  1880. set_font(font,turn_on,start,end)
  1881. int font;                /* flag for font to set (e.g. Bold) */
  1882. int turn_on;                /* should I start the font or end it?*/
  1883. char *end;                /* strings to start and */
  1884. char *start;                /* end the group that sets the font */
  1885. {
  1886.    if(turn_on && Cformatting_char) {
  1887.      if(!no_grouping) {
  1888.         push_LaTeX_stack(end,Font,font);
  1889.      }
  1890.      output_str(start,'\0');
  1891.    }
  1892. }
  1893.  
  1894. /*****************************************************************************
  1895.  *
  1896.  * change fontsize
  1897.  */
  1898. void set_fontsize(fontsize)
  1899. int fontsize;                /* size of fonts default 10 */
  1900. {
  1901. if (fontsize<0)
  1902.     {
  1903.     p6("set_fontsize\nfontsize<0");
  1904.     return;
  1905.     }
  1906. if (fontsize==0)
  1907.     {
  1908.     p6("set_fontsize\nfontsize==0");
  1909.     return;
  1910.     }
  1911. if (!Cformatting_char)
  1912.     {
  1913.     return;
  1914.     }
  1915. if (fontsize==8)
  1916.     {
  1917.     (void)RTFGetToken();
  1918.     if (strcmp(rtfTextBuf,"\\up6")==0)
  1919.         {
  1920.         RTFUngetToken();
  1921.         return;            /* mostly we are before a footnote here */
  1922.         }                       /* so we need no size-command, because */
  1923.     RTFUngetToken();                /* LaTeX deel in a good way with it */
  1924.     }
  1925. fputc('%',stdout);
  1926. output('\n',1);
  1927. if (initialised)            /* in newenvironment {} not necessary */
  1928.     {
  1929.     push_LaTeX_stack("}",Font,0);
  1930.     output_str("{",'\0');
  1931.     }
  1932. if (fontsize<5)
  1933.     {
  1934.     output_str("\\tiny ",'\0');
  1935.     return;
  1936.     }
  1937. if (fontsize<7)
  1938.     {
  1939.     output_str("\\scriptsize ",'\0');
  1940.     return;
  1941.     }
  1942. if (fontsize<9)
  1943.     {
  1944.     output_str("\\small ",'\0');
  1945.     return;
  1946.     }
  1947. if (fontsize<11)
  1948.     {
  1949.     output_str("\\normalsize ",'\0');
  1950.     return;
  1951.     }
  1952. if (fontsize<13)
  1953.     {
  1954.     output_str("\\large ",'\0');
  1955.     return;
  1956.     }
  1957. if (fontsize<17)
  1958.     {
  1959.     output_str("\\Large ",'\0');
  1960.     return;
  1961.     }
  1962. if (fontsize<21)
  1963.     {
  1964.     output_str("\\LARGE ",'\0');
  1965.     return;
  1966.     }
  1967. if (fontsize<25)
  1968.     {
  1969.     output_str("\\huge ",'\0');
  1970.     return;
  1971.     }
  1972. output_str("\\Huge ",'\0');
  1973. }
  1974.  
  1975.  
  1976. /*****************************************************************************
  1977.  *
  1978.  * set higher or lower text
  1979.  */
  1980.  
  1981. static void
  1982. set_subsuper(param)
  1983. int param;
  1984. {
  1985.       if(param == 0)
  1986.      {        /* end of a sub/superscript */
  1987.      while(!top_LaTeX_flags(Sub_Super))
  1988.         {
  1989.         if(pop_LaTeX_stack() == 0)
  1990.            {
  1991.            if(verbose)
  1992.           {
  1993.           fprintf(stderr,"%s: Failed to find end of sub/superscript\n",
  1994.             progname);
  1995.           }
  1996.            return;
  1997.            }
  1998.          }
  1999.      pop_LaTeX_stack();        /* pop off the '}' */
  2000.      if(top_LaTeX_flags(Math)) pop_LaTeX_stack(); /* and pop math too */
  2001.      return;
  2002.      }
  2003.       if (rtfMinor == rtfSuperScript)
  2004.           {
  2005.           (void)RTFGetToken();
  2006.           if (strcmp(rtfTextBuf,"\\chftn")==0)
  2007.          return;         /* we are before a footnote here */
  2008.           RTFUngetToken();        /* so we need no command, because */
  2009.           }             /* LaTeX deels with it in a good way */
  2010.       output_str("$",'\0');
  2011.       push_LaTeX_stack("$",Sub_Super,1);
  2012.       if (initialised)
  2013.           {
  2014.           output_str(rtfMinor == rtfSuperScript ? "^{" : "_{",'\0');
  2015.           push_LaTeX_stack("}",Sub_Super,rtfParam);
  2016.           }
  2017.       else
  2018.           {
  2019.           output_str(rtfMinor == rtfSuperScript ? "^" : "_",'\0');
  2020.           output_str(" \\bgroup",'\0');
  2021.           push_LaTeX_stack(" \\egroup",Sub_Super,rtfParam);
  2022.           }
  2023. }
  2024. /*****************************************************************************
  2025.  *
  2026.  * set smallcaps
  2027.  */
  2028.  
  2029. static void
  2030. set_smallcaps()
  2031. {
  2032. fputc('%',stdout);
  2033. output('\n',1);
  2034. if (initialised)
  2035.       {
  2036.       output_str("{",'\0');
  2037.       push_LaTeX_stack("}",Font,0);
  2038.       }
  2039. output_str("\\sc ",'\0');
  2040. }
  2041.  
  2042. /*****************************************************************************
  2043.  *
  2044.  * Print a string, ensuring that we are in math mode at the time
  2045.  */
  2046. static void
  2047. in_math(str)
  2048. char *str;
  2049. {
  2050.       output('$',0);
  2051.       output_str(str,'\0');
  2052.       output('$',0);
  2053. }
  2054.  
  2055. /*****************************************************************************
  2056.  *
  2057.  * Write a character, filling the the output text as we go. Characters
  2058.  * special to LaTeX are treated appropriately.
  2059.  */
  2060. #define FILL_COLUMN 60            /* column to fill to */
  2061. #define MAX_COLUMN 80            /* max of column*/
  2062. static int column=0;            /* current column */
  2063. static void
  2064. output(c,quote)
  2065. int c;                    /* The char to print */
  2066. int quote;                /* quote LaTeX's special chars? */
  2067. {
  2068.    char temp[25];
  2069.    c &= '\377';                /* prevent sign extension */
  2070.    
  2071.    if(isspace(c))
  2072.       {
  2073.       if(c == '\n')
  2074.     {
  2075.     fputc('\n',stdout);
  2076.     column=0;
  2077.     }
  2078.       else
  2079.     {
  2080.     fputc(' ',stdout);
  2081.     column++;
  2082.     if (column>FILL_COLUMN)
  2083.         {
  2084.         fputc('\n',stdout);
  2085.         column=0;
  2086.         }
  2087.     }
  2088.       return;
  2089.       }
  2090.  
  2091.    if(quote) {
  2092.       switch (rtf_ptr->char_attr.FontType) {
  2093.        case rtfFFTech:            /* A technical font */
  2094.      {
  2095.         char *str;
  2096.         
  2097.         str = (c < 128) ? symbol[c] : symbol8[c & '\177'];
  2098.         if(*str == '\0') {
  2099.            /* if(verbose) { */
  2100.           fprintf(stderr,"%s: Unknown Tech character: 0x%x\n",
  2101.             progname,c);
  2102.            /* } */
  2103.         }
  2104.         if(verbose) {
  2105.           fprintf(stderr,"A Tech character: 0x%x\n",c);
  2106.         }
  2107.         in_math(str);
  2108.      }
  2109.      return;
  2110.        default:
  2111.      switch (c)
  2112.       {            /* deal with various characters */
  2113.       case '%': case '$':
  2114.       case '#': case '&':
  2115.       case '_':
  2116.         fputc('\\',stdout);
  2117.         column++;
  2118.         break;
  2119.       case '^':
  2120.         output_str("$^{\\wedge}$",'\0');
  2121.         return;
  2122.       case '"':
  2123.         if(translate_quotes)
  2124.         c = (quotecount++ % 2) ? '\'' : '`';
  2125.         else
  2126.         c = '`';
  2127.         fputc(german_dquotes ? '"' : c, stdout);
  2128.         column++;
  2129.         break;
  2130.       case '<': case '>':
  2131.       case '|':
  2132.         sprintf(temp,"%c",c);
  2133.         in_math(temp);
  2134.         return;
  2135.       case '{': case '}':
  2136.         sprintf(temp,"\\%c",c);
  2137.         in_math(temp);
  2138.         return;
  2139.       case '\\':     
  2140.         in_math("\\backslash");
  2141.         return;
  2142.       case '~':
  2143.         in_math("\\sim");
  2144.         c = ' ';
  2145.         return;
  2146.       default:
  2147.         if(!isascii(c))
  2148.            {
  2149.            output_8bit(c);
  2150.            return;
  2151.            }
  2152.         if(!isalnum(c) && !ispunct(c))
  2153.            {
  2154.            if (verbose)
  2155.           fprintf(stderr,"%s: Unknown 7-bit character: 0x%x\n",
  2156.              progname,c);
  2157.            return;
  2158.            }
  2159.         break;
  2160.      }
  2161.       }
  2162.    }
  2163. fputc(c,stdout);
  2164. column++;
  2165. }
  2166. /*****************************************************************************
  2167.  *
  2168.  * Output an entire word, without trying to quote any special characters.
  2169.  * The character C is then output using output(), which allows proper page
  2170.  * breaks.
  2171.  */
  2172.  
  2173. static void
  2174. output_str(str,c)
  2175. char *str;
  2176. int c;
  2177. {
  2178. int len = strlen(str);
  2179. int zeiger=0;
  2180. if(c != '\0')
  2181.       {
  2182.       output(c,1);
  2183.       }
  2184. if (column==0 && str[0]=='\n')
  2185.       str++;
  2186. if (str[0]=='\n')
  2187.     fputc('%',stdout);
  2188. fprintf(stdout,"%s",str);
  2189. column+=len;
  2190. if (str[0] =='\n')
  2191.     column=len;
  2192. if (str[len-1] == '\n')
  2193.     column=0;
  2194. }
  2195.  
  2196. /*****************************************************************************
  2197.  *
  2198.  * Deal with special characters above \177.
  2199.  */
  2200.  
  2201.  
  2202. typedef struct Char8bit
  2203. {
  2204. int nr;                    /* RTF-code */
  2205. char *str;                            /* LaTeX command  */
  2206. struct Char8bit *next;
  2207. }char8;
  2208.  char8 *list_8bit;            /* begin of the 8bit list */
  2209.  char8 *help;
  2210.  
  2211.  
  2212. /*****************************************************************************
  2213.  *
  2214.  *   write a 8bit character
  2215.  */
  2216.  
  2217. static void
  2218. output_8bit(c)
  2219. int c;
  2220. {
  2221.    char *str;
  2222.  
  2223. help=list_8bit;
  2224. while(help->nr!=c && help->next!=NULL)        /* search for the character*/
  2225.     help=help->next;
  2226. if (help->nr==c)
  2227.       {
  2228.       output_str(help->str,'\0');            /* and write it */
  2229.       }
  2230. else
  2231.       {                                        /* character not found */
  2232.       if(verbose)
  2233.      {
  2234.      static count=0;
  2235.      fprintf(stderr,"%s: Unknown 8-bit character: 0x%x\n",progname,c);
  2236.      if (count++<1||verbose>1)
  2237.         fprintf(stderr,"   Have a look in the file .cod\n");
  2238.      }
  2239.       }
  2240. }
  2241. /*****************************************************************************
  2242.  *
  2243.  *   read the file mac.code (or an other file e.g. ansi.code: use flag -C) 
  2244.  *   and store the commands for characters with the 8bit set in the list
  2245.  *   "list_8bit"
  2246.  */
  2247.  
  2248.  
  2249. static void
  2250. read_code_file(codefile)
  2251. char *codefile;
  2252. {
  2253.  
  2254. char line[line_length];
  2255. int pos;
  2256.  
  2257. open_code_file(codefile);
  2258. if (fgets(line,line_length,fpcode)==NULL)
  2259.     {
  2260.     fprintf(stderr,"\n%s: Incorrect file a8bit    \
  2261.             \nat first there must be a number of the ascii character with msb set  \
  2262.             \n(between 128 and 255)\n",progname);
  2263.     exit(1);
  2264.     }
  2265.     for (pos=23;line[pos]==' ';pos--);
  2266.     line[pos+1]='\0';            /* cut the comment in the file*/
  2267.     list_8bit=(struct Char8bit *)malloc((int)sizeof(struct Char8bit));
  2268.     if (list_8bit==(struct Char8bit *)NULL)
  2269.         {
  2270.         fprintf(stderr,"%s: TCErr - cannot allocate a 8bit-character name\n", progname);
  2271.         exit(1);
  2272.                 }
  2273.     sscanf(line,"%d",&(list_8bit->nr));
  2274.     list_8bit->str=StrSave(line+4);
  2275.     if (list_8bit->nr<128 || list_8bit->nr>255)
  2276.         {
  2277.         fprintf(stderr,"\n%s: Incorrect file a8bit  \
  2278.                 \nat first there must be a number of the ascii character with msb set  \
  2279.                 \n(between 128 and 255)\n", progname);
  2280.         exit(1);
  2281.         }
  2282.     list_8bit->next=NULL;
  2283. while (fgets(line,line_length,fpcode)!=NULL)
  2284.     {
  2285.     for (pos=23;line[pos]==' ';pos--);
  2286.     line[pos+1]='\0';
  2287.     help=(struct Char8bit *)malloc((int)sizeof(struct Char8bit));
  2288.     if (help==(struct Char8bit *)NULL)
  2289.         {
  2290.         fprintf(stderr,"%s: SSErr - cannot allocate a 8bit-character name\n", progname);
  2291.         exit(1);
  2292.                 }
  2293.     help->next=list_8bit;
  2294.     list_8bit=help;
  2295.     sscanf(line,"%d",&(list_8bit->nr));
  2296.     list_8bit->str=StrSave(line+4);
  2297.     if (list_8bit->nr<128 || list_8bit->nr>255)
  2298.         {
  2299.         fprintf(stderr,"\n%s: Incorrect file a8bit  \
  2300.                 \nat first there must be a number of the ascii character with msb set  \
  2301.                 \n(between 128 and 255)\n", progname);
  2302.         exit(1);
  2303.                 }
  2304.     }
  2305. if (fpcode!=NULL) fclose(fpcode);
  2306. }
  2307.  
  2308.  
  2309. /*****************************************************************************
  2310.  *
  2311.  * write an errormassage to stderr
  2312.  *
  2313.  */
  2314. static void
  2315. p6(proc_name)
  2316. char *proc_name;    /*name of ther procedure where the mistake must be */
  2317. {
  2318.      fprintf(stderr," %s: Problem in procedure %s\n",progname,proc_name);
  2319.      fprintf(stderr,"           please call Erwin Wechtl\n");
  2320.      fprintf(stderr,"                       W""ortgasse 2/18\n");
  2321.      fprintf(stderr,"                       A-2500 Baden\n");
  2322.      fprintf(stderr,"                       Austria\n");
  2323.      fprintf(stderr,"                       Tel.: 43/2252/44686\n");
  2324. }
  2325.  
  2326. /*****************************************************************************
  2327.  *
  2328.  * set end af table
  2329.  */
  2330.  
  2331. static void
  2332. end_table()
  2333. {
  2334.     table_mode=0;
  2335.     if (top_LaTeX_flags(Tabular))
  2336.         {
  2337.         Cformatting_char=formatting_char;
  2338.         Cformatting_para=formatting_para;
  2339.         pop_LaTeX_stack();
  2340.         tabinitold[0]='\0';
  2341.         output_str("\n  \n",'\0');
  2342.         }
  2343. }
  2344.  
  2345.  
  2346. /*****************************************************************************
  2347.  *
  2348.  *  translate each RTF-style into a new LaTeX environment
  2349.  *  and look for special WORD styles like heading (tranlated into section)
  2350.  *  or footer (ignored)
  2351.  */
  2352. LATEXStyle *LaTeXstyleList;        /* we can't use the RTFstylelist
  2353.                        because we need more variables */
  2354.  
  2355. void DefineStyles()
  2356. {
  2357. RTFStyle   *rtfstyle;            /* the style to deel with */
  2358. LATEXStyle *LaTeXstyle;            /* the style to deel with */
  2359.  
  2360. output_str("\n \n",'\0');
  2361. LaTeXstyleList=(LATEXStyle *)NULL;
  2362. for(rtfstyle=RTFGetStyle(-1);rtfstyle!=(RTFStyle *)NULL;rtfstyle=rtfstyle->rtfNextStyle)
  2363.    {
  2364.    LaTeXstyle=(LATEXStyle *)malloc(sizeof(struct LATEXStyle));
  2365.    if (LaTeXstyle==NULL)
  2366.     {
  2367.     fprintf(stderr,"\n%s: Can't alloc LaTeXstyle\n",progname);
  2368.     exit(1);
  2369.     }
  2370.    LaTeXstyle->stacktype=Undefined;
  2371.    LaTeXstyle->BeginCommand[0] = LaTeXstyle->EndCommand[0] = '\0';
  2372.    LaTeXstyle->special_WinwordStyle=TRUE;
  2373.    if (!is_specialWORDstyle(rtfstyle,LaTeXstyle))      /* looking for special styles */
  2374.     {
  2375.     char commandbuf[80];
  2376.     RTF_STACK rtf_save;
  2377.  
  2378.     push_rtf_group();
  2379.     rtf_save = rtf_current;
  2380.     LaTeXstyle->special_WinwordStyle=FALSE;
  2381.     LaTeX_name(rtfstyle->rtfSName);
  2382.     strcpy(commandbuf,"\n\\");
  2383.     strcat(commandbuf,"begin{");
  2384.     strcat(commandbuf,rtfstyle->rtfSName);
  2385.     strcat(commandbuf,"}\n");
  2386.     strcpy(LaTeXstyle->BeginCommand,commandbuf);
  2387.     strcpy(commandbuf,"\n\\");
  2388.     strcat(commandbuf,"end{");
  2389.     strcat(commandbuf,rtfstyle->rtfSName);
  2390.     strcat(commandbuf,"}\n");
  2391.     strcpy(LaTeXstyle->EndCommand,commandbuf);
  2392.  
  2393.     output_str("\n% definition of ",'\0');
  2394.     output_str(rtfstyle->rtfSName,'\0');
  2395.     output_str("\n\\newenvironment{",'\0');
  2396.     output_str(rtfstyle->rtfSName,'\0');
  2397.     output_str("}{",'\0');
  2398.  
  2399.     RTFExpandStyle(rtfstyle->rtfSNum);
  2400.     LaTeXstyle->char_attr=rtf_ptr->char_attr;
  2401.     LaTeXstyle->par_attr=rtf_ptr->par_attr;
  2402.     LaTeXstyle->stacktype=NormalWORDstyle;
  2403.     update_current();
  2404.     output_str("}{",'\0');
  2405.     while(pop_LaTeX_stack()) continue;
  2406.     output_str("}\n",'\0');
  2407.  
  2408.     rtf_current = rtf_save;
  2409.     pop_rtf_group();
  2410.     }
  2411.   LaTeXstyle->rtfSNum=rtfstyle->rtfSNum;
  2412.   LaTeXstyle->rtfSName=rtfstyle->rtfSName;
  2413.   LaTeXstyle->LaTeXNextStyle=LaTeXstyleList;
  2414.   LaTeXstyleList=LaTeXstyle;
  2415.    }
  2416. if (fpland!=NULL) fclose(fpland);
  2417. }
  2418.  
  2419. /*****************************************************************************
  2420.  *
  2421.  *   begin a style environment
  2422.  */
  2423.  
  2424.  
  2425. void setstylecommand(n)
  2426. int    n;            /* rtfStyleNumber */
  2427. {
  2428. LATEXStyle    *LaTeXstyle;
  2429. RTFStyle        *rtfstyle;
  2430. char buf[80];
  2431.  
  2432.     if(!table_mode && top_LaTeX_flags(Tabular))
  2433.         end_table();
  2434.     LaTeXstyle=LaTeXstyleList;
  2435.     while (LaTeXstyle!=NULL && LaTeXstyle->rtfSNum!=n) LaTeXstyle=LaTeXstyle->LaTeXNextStyle;
  2436.     if (LaTeXstyle==NULL)
  2437.         {
  2438.         static int count=0;
  2439.  
  2440.         rtfstyle=RTFGetStyle(n);
  2441.         if (verbose>1 || (verbose && count++==0))
  2442.             {
  2443.             fprintf(stderr,"%s: There are some troubles with the style %s with the number %d, \n  so this style is ignored\n",
  2444.                 progname,rtfstyle->rtfSName,n);
  2445.             }
  2446. # ifdef notdef /* Don't know if this is needed anymore */
  2447. /*        sprintf(buf,"\n%% The Style %s with the number %d may begin here\n",rtfstyle->rtfSName,n);
  2448.         output_str(buf,'\0');
  2449.         output_str("%%But rtf2LaTeX has had some troubles with it",'\0');
  2450.         sprintf(buf,"\n%  The Style %s with the number %d may end here\n",rtfstyle->rtfSName,n);
  2451.         push_LaTeX_stack(buf,NormalWORDstyle,0);
  2452. */
  2453. # endif /* notdef */
  2454.         return;
  2455.         }
  2456.     if (LaTeXstyle->special_WinwordStyle)    /* if heading,footer, ... */
  2457.         {       /* use paragraph(character) formating only
  2458.                if the flag -d is on             */
  2459.         Cformatting_para=formatting_sWORD&&formatting_para;
  2460.         Cformatting_char=formatting_sWORD&&formatting_char;
  2461.         }
  2462.     else
  2463.         {
  2464.         update_current();    /* format */
  2465.         rtf_current.par_attr=LaTeXstyle->par_attr;
  2466.         rtf_current.char_attr=LaTeXstyle->char_attr;
  2467.         rtf_ptr->par_attr=LaTeXstyle->par_attr;
  2468.         rtf_ptr->char_attr=LaTeXstyle->char_attr;
  2469.         rtf_current.LaTeX_stack = NULL;
  2470.         rtf_current.prev = NULL;
  2471.         }
  2472.     output_str(LaTeXstyle->BeginCommand,'\0');
  2473.     push_LaTeX_stack(LaTeXstyle->EndCommand,LaTeXstyle->stacktype,0);
  2474. }
  2475.  
  2476. /*****************************************************************************
  2477.  *
  2478.  *  look in the file english.land (or an other file e.g. german.land:
  2479.  *  use flag -L) 
  2480.  *  if this is a Spezial WORD style like heading, footer, ...
  2481.  */
  2482.  
  2483.  
  2484. int
  2485. is_specialWORDstyle(rtfstyle,LaTeXstyle)
  2486. RTFStyle    *rtfstyle;
  2487. LATEXStyle    *LaTeXstyle;
  2488.  
  2489. {
  2490. char line[line_length];                         /* the line which is read from the file */
  2491.  
  2492. if (formatting_sWORD)                /* if flag -d is on */
  2493.     return(0);                /* use WORD formate instead of LaTeX formate within header, ... */
  2494. fseek(fpland, 0, SEEK_SET);
  2495. while (fgets(line,line_length,fpland)!=NULL)
  2496.     {
  2497.     if (strncmp(rtfstyle->rtfSName,line,strlen(rtfstyle->rtfSName))==0)
  2498.         {
  2499.         LaTeXstyle->stacktype=SpecialWORDstyle;
  2500.         if (strncmp(line+20,"           ",10)!=0)
  2501.             sscanf(line+20,"%20s%20s",LaTeXstyle->BeginCommand,LaTeXstyle->EndCommand);
  2502.         else
  2503.             LaTeXstyle->BeginCommand[0] = LaTeXstyle->EndCommand[0] = '\0';
  2504.         output_str("% ",'\0');
  2505.         output_str(line+60,'\0');
  2506.         return(1);
  2507.         }
  2508.     }
  2509. return(0);
  2510. }
  2511.  
  2512. /*****************************************************************************
  2513.  *
  2514.  *   malloc for a string
  2515.  */
  2516.  
  2517.  
  2518. static char *StrSave (s)
  2519. char    *s;
  2520. {
  2521. char    *p;
  2522.  
  2523.     if ((p = (char *)malloc (strlen (s) + 1)) == (char *) NULL)
  2524.         fprintf(stderr,"%s: Error in malloc\n",progname);
  2525.     return (strcpy (p, s));
  2526. }
  2527.  
  2528.  
  2529. /*****************************************************************************
  2530.  *
  2531.  *   set the position of the Tabstops and output the begin environment
  2532.  */
  2533.  
  2534.  
  2535. static void
  2536. start_tabstops()
  2537. {
  2538.    int i,j;
  2539.    int width;                /* width of table entry (twips) */
  2540.    char buf[1];
  2541.  
  2542.    if (top_LaTeX_flags(SpecialWORDstyle)) 
  2543.     return;               /* no tab stops in header, heading, ...*/
  2544.    Cformatting_char=formatting_char&&formatting_table;
  2545.    Cformatting_para=formatting_para&&formatting_table;
  2546.    output_str("\n\\begin{tabbing}\n",'\0');
  2547.    for(i = 0;i < NTABS;i++)
  2548.       {
  2549.       width = tabstops[i].pos;
  2550.       if(i > 0)
  2551.     width -= tabstops[i - 1].pos;
  2552.       width=TW_TO_CA(width);
  2553.       if (width<1)
  2554.     continue;
  2555.       for(j=1;j<=width;j++)
  2556.     {
  2557.     sprintf(buf,"%d",(j % 10));
  2558.     output_str(buf,'\0');
  2559.     }
  2560.       output_str("\\=",'\0');
  2561.       }
  2562.    output_str("\\kill\n",'\0');
  2563.    push_LaTeX_stack("\\end{tabbing}\n",Tabstops,0);
  2564.    tabstopsInit();
  2565.    tab=2;
  2566. }
  2567.  
  2568. /*****************************************************************************
  2569.  *
  2570.  *   initialise the array of the Tabstops-positions
  2571.  */
  2572.  
  2573. static void
  2574. tabstopsInit()
  2575. {
  2576. int i;
  2577.  
  2578. for (i=0;i<NTABS;i++)
  2579.     {
  2580.     tabstops[i].pos=CA_TO_TW(i*defaultTabWidth);
  2581.     tabstops[i].type=0;
  2582.     }
  2583.     ntabs=0;
  2584. }
  2585.  
  2586. /*****************************************************************************
  2587.  *
  2588.  * Stack stuff -- RTF and LaTeX grouping go on separate stacks
  2589.  *
  2590.  * pop the status stack, putting the free'd element on the free list
  2591.  */
  2592. static RTF_STACK *rtf_free_list = NULL;
  2593. static void
  2594. pop_rtf_group()
  2595. {
  2596.    RTF_STACK *temp;
  2597.    
  2598.    if(rtf_ptr->prev == NULL) {
  2599.       fprintf(stderr,"%s: Attempt to pop an empty stack\n", progname);
  2600.       abort();
  2601.    }
  2602.    temp = rtf_ptr->prev;
  2603.    rtf_ptr->prev = rtf_free_list;
  2604.    rtf_free_list = rtf_ptr;
  2605.    rtf_ptr = temp;
  2606. }
  2607. /*
  2608.  * push the RTF status stack
  2609.  */
  2610. static void
  2611. push_rtf_group()
  2612. {
  2613.    RTF_STACK *temp;
  2614.    
  2615.    if(rtf_free_list != NULL) {
  2616.       temp = rtf_free_list;
  2617.       rtf_free_list = rtf_free_list->prev;
  2618.    } else {
  2619.       if((temp = (RTF_STACK *)malloc(sizeof(RTF_STACK))) == NULL) {
  2620.      fprintf(stderr,"%s: Can't allocate storage for stack\n",progname);
  2621.      exit(1);
  2622.       }
  2623.    }
  2624.    memcpy((char *)temp,(char *)rtf_ptr,sizeof(RTF_STACK));
  2625.    temp->prev = rtf_ptr;
  2626.    rtf_ptr = temp;
  2627.    rtf_ptr->LaTeX_stack = NULL;
  2628. }
  2629. /*****************************************************************************
  2630.  *
  2631.  * Now the LaTeX stacks. Use the stack in the current rtf_ptr frame
  2632.  */
  2633. static LATEX_STACK *myTeX_free_list = NULL;
  2634. static int
  2635. pop_LaTeX_stack()
  2636. {
  2637.    char *str;
  2638.    LATEX_STACK *temp;
  2639.    
  2640.    if(rtf_ptr->LaTeX_stack == NULL) {
  2641.       return(0);
  2642.    }
  2643.    if (rtf_ptr->LaTeX_stack->type == SpecialWORDstyle)
  2644.     {                    /* reset formatting      */
  2645.     Cformatting_para =formatting_para;    /* after heading, footer, .. */
  2646.     Cformatting_char=formatting_char;
  2647.     }
  2648.    LaTeX_group--;
  2649.    str = rtf_ptr->LaTeX_stack->str;
  2650.    temp = rtf_ptr->LaTeX_stack->prev;
  2651.    rtf_ptr->LaTeX_stack->prev = myTeX_free_list;
  2652.    myTeX_free_list = rtf_ptr->LaTeX_stack;
  2653.    rtf_ptr->LaTeX_stack = temp;
  2654.    output_str(myTeX_free_list->str,'\0');
  2655.    return(1);
  2656. }
  2657. /*
  2658.  * push the string STR onto the LaTeX stack, with attributes TYPE and FLAGS
  2659.  */
  2660. static void
  2661. push_LaTeX_stack(str,type,flags)
  2662. char *str;                /* string to save */
  2663. int type;                /* type of string */
  2664. long flags;                /* and corresponding flags */
  2665. {
  2666.    LATEX_STACK *temp;
  2667.    LaTeX_group++;
  2668.    if(myTeX_free_list != NULL) {
  2669.       temp = myTeX_free_list;
  2670.       myTeX_free_list = myTeX_free_list->prev;
  2671.    } else {
  2672.       if((temp = (LATEX_STACK *)malloc(sizeof(LATEX_STACK))) == NULL) {
  2673.      fprintf(stderr,"%s: Can't allocate storage for stack\n",progname);
  2674.      exit(1);
  2675.       }
  2676.    }
  2677.    
  2678.    temp->prev = rtf_ptr->LaTeX_stack;
  2679.    rtf_ptr->LaTeX_stack = temp;
  2680.    rtf_ptr->LaTeX_stack->str = str;
  2681.    rtf_ptr->LaTeX_stack->type = type;
  2682.    rtf_ptr->LaTeX_stack->flags = flags;
  2683.    return;
  2684. }
  2685. /*****************************************************************************
  2686.  *
  2687.  * Return the flags of the proper type for the top element of the LaTeX stack
  2688.  */
  2689. static int
  2690. top_LaTeX_flags(type)
  2691. int type;
  2692. {
  2693.    return((rtf_ptr->LaTeX_stack != NULL && rtf_ptr->LaTeX_stack->type == type) ?
  2694.       1 : 0);
  2695. }
  2696. /*****************************************************************************/
  2697.  
  2698.  
  2699. static void
  2700. open_code_file (codefile)
  2701. char *codefile;
  2702. {
  2703.       char *filename;
  2704.       char line[line_length];
  2705.       char c;
  2706.       if((filename = malloc(strlen(codefile) + strlen(RTFDIR) + 7)) == NULL)
  2707.       {
  2708.     fprintf(stderr,"%s: Error in malloc\n",progname);
  2709.     exit(3);
  2710.       }
  2711.       strcpy(filename,RTFDIR);
  2712. #if !defined (THINK_C)
  2713.       strcat(filename,"/");
  2714. #endif /* !THINK_C */
  2715.       strcat(filename,codefile);
  2716.       if ((strchr(codefile,'.')) == NULL)
  2717.           strcat(filename,".code");
  2718.       if((fpcode = fopen(filename,"r")) == NULL)
  2719.      {
  2720.      fprintf(stderr,"%s: Can't open %s\n",progname,filename);
  2721.      exit(1);
  2722.      }
  2723.       free(filename);
  2724.       if (fgets(line,line_length,fpcode)==NULL)
  2725.     {
  2726.     fprintf(stderr,"\n%s: Incorrect file a8bit   \
  2727.             \nthere must be a comment in the first line\n",
  2728.             progname);
  2729.     exit(1);
  2730.     }
  2731. }
  2732. static void
  2733. open_land_file (landfile)
  2734. char *landfile;
  2735. {
  2736.       char *filename;
  2737.       if((filename = malloc(strlen(landfile) + strlen(RTFDIR) + 7)) == NULL)
  2738.       {
  2739.     fprintf(stderr,"%s: Error in malloc\n",progname);
  2740.     exit(3);
  2741.       }
  2742.       strcpy(filename,RTFDIR);
  2743. #if !defined (THINK_C)
  2744.       strcat(filename,"/");
  2745. #endif /* !THINK_C */
  2746.       strcat(filename,landfile);
  2747.       if ((strchr(landfile,'.')) == NULL)
  2748.           strcat(filename,".land");
  2749.       if((fpland = fopen(filename,"r")) == NULL) {
  2750.      fprintf(stderr,"%s: Can't open %s\n",progname,filename);
  2751.      exit(1);
  2752.       }
  2753.       free(filename);
  2754. }
  2755.